package me.shiqiang.im;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.InvalidParameterException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 根据twitter雪花ID生成器思想编写的分布式ID生成器
 *
 * @author cuishiqiang
 * @date 2018/1/12 下午4:04
 */
public class SnowFlake {

//    Logger logger = LoggerFactory.getLogger(this.getClass());
    static Logger logger = LoggerFactory.getLogger(SnowFlake.class);

    public SnowFlake(long machineId) {
        if (machineId > MACHINE_MAX_NUM) {
            throw new InvalidParameterException("参数不可以大于机器最大数：" + MACHINE_MAX_NUM);
        }
        this.machineId = machineId;
    }

    /** 起始时间戳 */
    private static final long start_ts = 1514736000000L;

    private static final long MACHINE_BIT = 12L;
    private static final long SEQ_BIT = 10L;

    /**
     * 获取每段的最大值
     * 拿int类型举例（long类型原理一致）
     * -1 二进制表示 11111111 11111111 11111111 11111111 共32位
     * -1 << 5 算数位移5位后  11111111 11111111 11111111 11100000
     * ~(-1 << 5) 对结果取反 00000000 00000000 00000000 00011111；11111 转换为10进制 2^6-1 = 31
     */
    public static final long MACHINE_MAX_NUM = ~(-1L << MACHINE_BIT);
    private static final long SEQ_MAX_NUM = ~(-1L << SEQ_BIT);

    private static final long MACHINE_SHIFT = SEQ_BIT;
    private static final long TS_SHIFT = MACHINE_SHIFT + MACHINE_BIT;

    //    private long lastTs = System.currentTimeMillis();
    private AtomicLong lastTs = new AtomicLong(System.currentTimeMillis());
    private AtomicInteger seq = new AtomicInteger(1);
    private long machineId;

    public long nextId() {
        long currentTs = System.currentTimeMillis();
        long ts = lastTs.getAndSet(currentTs);
        int currentSeq;
        if (currentTs == ts) {
            currentSeq = seq.getAndIncrement();
        } else {
            seq.set(2);
            currentSeq = 1;
        }
        return (currentTs-start_ts) << TS_SHIFT | machineId << MACHINE_SHIFT | currentSeq;
    }


//    public SnowFlake(long machineId, long serverId) {
//        if (machineId > MACHINE_MAX_NUM) {
//            throw new InvalidParameterException("mechineId不可以大于机器最大数：" + MACHINE_MAX_NUM);
//        }
//        if (serverId > SERVER_MAX_NUM) {
//            throw new InvalidParameterException("serverId不可以大于服务器最大数：" + SERVER_MAX_NUM);
//        }
//        this.machineId = machineId;
//        this.serverId = serverId;
//    }
//
//    /** 起始时间戳 */
//    private static final long start_ts = 1514736000000L;// 2018 0101
//
//    private static final long MACHINE_BIT = 5L;
//    private static final long SERVER_BIT = 5L;
//    private static final long SEQ_BIT = 12L;
//
//    /**
//     * 获取每段的最大值
//     * 拿int类型举例（long类型原理一致）
//     * -1 二进制表示 11111111 11111111 11111111 11111111 共32位
//     * -1 << 5 算数位移5位后  11111111 11111111 11111111 11100000
//     * ~(-1 << 5) 对结果取反 00000000 00000000 00000000 00011111；11111 转换为10进制 2^6-1 = 31
//     */
//    private static final long MACHINE_MAX_NUM = ~(-1L << MACHINE_BIT);
//    private static final long SERVER_MAX_NUM = ~(-1L << SERVER_BIT);
//    private static final long SEQ_MAX_NUM = ~(-1L << SEQ_BIT);
//
//    private static final long MACHINE_SHIFT = SEQ_BIT;
//    private static final long SERVER_SHIFT = MACHINE_SHIFT + MACHINE_BIT;
//    private static final long TS_SHIFT = SERVER_SHIFT + SERVER_BIT;
//
//    //    private long lastTs = System.currentTimeMillis();
//    private AtomicLong lastTs = new AtomicLong(System.currentTimeMillis());
//    private AtomicInteger seq = new AtomicInteger(1);
//    private long machineId;
//    private long serverId;
//
//    public long nextId() {
//        long currentTs = System.currentTimeMillis();
//        long ts = lastTs.getAndSet(currentTs);
//        int currentSeq;
//        if (currentTs == ts) {
//            currentSeq = seq.getAndIncrement();
//        } else {
//            seq.set(2);
//            currentSeq = 1;
//        }
//        return (currentTs-start_ts) << TS_SHIFT | serverId << SERVER_SHIFT | machineId << MACHINE_SHIFT | currentSeq;
//    }


//    public static void main(String[] args) throws InterruptedException, ParseException {
////        System.out.println(DateUtils.parseDate("20180101","yyyyMMdd").getTime());
//        long start = System.currentTimeMillis();
//        CountDownLatch countDownLatch = new CountDownLatch(1000);
//        for (int i = 1; i <= 1000; i++) {
//            int finalI = i;
//            new Thread(() -> {
//                SnowFlake snowFlake = new SnowFlake(finalI);
//                int count = 0;
//                while (true) {
////                    logger.info(String.valueOf(snowFlake.nextId()));
//                    System.out.println(String.valueOf(snowFlake.nextId()));
//                    count++;
//                    if (count == 1000) {
//                        countDownLatch.countDown();
//                        System.out.println(Thread.currentThread()+"退出");
//                        break;
//                    }
//                }
//            },"Thread"+i).start();
//        }
//        countDownLatch.await();
//        long end = System.currentTimeMillis();
//        System.out.println("耗时：" + (end - start));
//    }
}
